package gregorytersoff_model;

import java.util.ArrayList;


public class Model 
{
	private int numoptions;
	private Line[] lines;
	private Edge[] edges;
	private int rounds;
	private int currentround;
	private boolean readytogo;
	private int partofround;
	private boolean allfinished;
	private ArrayList<String> setnames;
	private boolean noconflicts;
	
	
	/**Model stores all data not stored in the various GUIs in the JFrame. It also establishes whether an added edge is valid, and determines
	 * the final result of the decisionline using the array of Line and Edge, and the methods used in each class
	 * 
	 * @param o The number of different options to use. As the program is intended to be used with one option per person, it is also used to
	 * decide the number of edges to add in a round
	 * @param r The number of rounds to add edges in
	 */
	public Model(int o, int r)
	{
		numoptions = o;
		rounds = r;
		currentround = 1;
		lines = new Line[numoptions];
		edges = new Edge[64];
		readytogo = false;
		allfinished = false;
		partofround = 0;
		setnames = new ArrayList<String>();
		noconflicts = false;
	}
	
	/**Allows access to the integer indicating the number of options
	 * 
	 * @return an integer indicating the number of options
	 */
	public int getNumoptions()
	{
		return numoptions;
	}
	/**Allows access to the integer indicating the initial width of the screen. Changing the return value will change the size of the screen, 
	 * and will cause various GUIs to be automatically moved or resized when the JFrame is first made 
	 * 
	 * @return an integer indicating the initial width of the screen
	 */
	public int getWidth()
	{
		return 1200;
	}
	/**Allows access to the integer indicating the initial height of the screen. Changing the return value will change the size of the screen, 
	 * and will cause various GUIs to be automatically moved or resized when the JFrame is first made 
	 * 
	 * @return an integer indicating the initial height of the screen
	 */
	public int getHeight()
	{
		return 698;
	}
	/**Allows access to the integer indicating the spacing used for lines, edges, choices, and edge-adding and error settingbuttons 
	 * 
	 * @return an integer indicating the spacing used for GUIs created based on the number of options
	 */
	public int getSpacing()
	{
		return (getWidth()-200)/34;
	}
	/**Allows access to the integer indicating the maximum number of rounds
	 * 
	 * @return an integer indicating the maximum number of rounds
	 */
	public int getRounds()
	{
		return rounds;
	}
	/**Allows access to the integer indicating the current number of rounds
	 * 
	 * @return an integer indicating the current number of rounds
	 */
	public int getCurrentRound()
	{
		return currentround;
	}
	/**Creates and stores the lines used in this instance of decisionlines, based on an array of strings containing the input of the user into
	 * the JTextFields
	 * 
	 * @param choices An array containing the list of names, in order, of each choice
	 */
	public void setLines(String[] choices)
	{
		for(int i = 0; i < numoptions; i++)
		{
			lines[i] = new Line(choices[i], i);
		}
		readytogo = true;
	}
	/**Allows access to the array of edges used
	 * 
	 * @return the Edge[] used to store the edges of this instance of decisionlines
	 */
	public Edge[] getEdges()
	{
		return edges;
	}
	
	/**Takes in one of the two lines the edge connects and a height, and if the edge is valid, adds that edge to an array of length 64 (the 
	 * location of which corresponds to the height of the edge, with the height field as a backup measure and to make passing information easier)
	 * and sends the edge back to the controller that called it so that it can be added to the LineCanvas, or if the edge is invalid sends back
	 * an impossible edge to inform the controller not to make a new line on the LineCanvas
	 * 
	 * @param x The left of the two lines the edge to be added connects
	 * @param y The height of the edge to be added
	 * @return Either a copy of the edge to be added so that a corresponding line can be added to the LineCanvas, or an Edge with all fields
	 * set to negative values to let the controller know that the edge to be added was invalid, and that it should not be added to the LineCanvas
	 */
	public Edge setEdges(int x, int y)
	{
		if(edges[y] == null && y < 64 && y > -1 && x < numoptions-1 && x > -1)
		{
			edges[y] = new Edge(x, x + 1, y);
			partofround++;
			if(partofround == numoptions)
			{
				currentround++;
				partofround = 0;
			}
			else if(partofround > numoptions)
			{
				currentround++;
				partofround = 0;
				System.out.println("teh eff? extra edges that round?");
			}
			return edges[y];
		}
		else
		{
			return new Edge(-1, -1, -1);
			
		}
		
	}
	/**Allows access to the boolean indicating whether the decisionlines can now have edges added to it
	 * 
	 * @return a boolean indicating whether the decisionlines can now have edges added to it
	 */
	public boolean getStatus()
	{
		return readytogo;
	}
	
	/**Sets booleans to values preventing the addition of further edges, runs a helper function to figure out the results, then creates a string
	 * based on the results to display to the user
	 * 
	 * @return The string to be printed on the JLabel to inform the user of the results without having to check the console (since the size of
	 * the window means that on many computers, the window by default obscures the console in eclipse)
	 */
	public String finish()
	{
		readytogo = false;
		String[] results = solve();
		String finalinput = "Final results: 1 is " + results[0];
		for(int i = 1; i<results.length; i++)
		{
			finalinput = finalinput + ", " + (i+1) + " is "+ results[i];
		}
		allfinished = true;
		for(int j = 0; j<results.length; j++)
		{
			System.out.println(results[j]);
		}
		return finalinput;
	}
	/**Orders each line based on their respective placement in the final result, and returns an array of strings to be edited together to
	 * display the final result
	 * 
	 * @return an array containing the names of the lines, in the order of the end result
	 */
	public String[] solve()
	{
		String[] finalresults = new String[numoptions];
		for(int i = 0; i<lines.length; i++)
		{
			finalresults[lines[i].solveYourself(edges, 0)] = lines[i].getChoice();
		}
		return finalresults;
	}
	/**Allows access to the boolean indicating whether the decisionlines has been solved
	 * 
	 * @return a boolean indicating whether the decisionlines has been solved
	 */
	public boolean getAllFinished()
	{
		return allfinished;
	}
	
}
